home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / tools / build.c < prev    next >
C/C++ Source or Header  |  1990-07-15  |  17KB  |  571 lines

  1. /* This program takes the previously compiled and linked pieces of the
  2.  * operating system, and puts them together to build a boot diskette.
  3.  * The files are read and put on the boot diskette in this order:
  4.  *
  5.  *      bootblok:       the diskette boot program
  6.  *      kernel:         the operating system kernel
  7.  *      mm:             the memory manager
  8.  *      fs:             the file system
  9.  *      init:           the system initializer
  10.  *      menu:           the selection menu
  11.  *
  12.  * The bootblok file goes in sector 0 of the boot diskette.  The operating system
  13.  * begins directly after it.  The kernel, mm, fs, init, and menu are each
  14.  * padded out to a multiple of CLICK_SIZE bytes, and then concatenated into a
  15.  * single file beginning 512 bytes into the file.  The first byte of sector 1
  16.  * contains executable code for the kernel.  There is no header present.
  17.  *
  18.  * After the boot image has been built, build goes back and makes several
  19.  * patches to the image file or diskette:
  20.  *
  21.  *      1. The last 4 words of the boot block are set as follows:
  22.  *       Word at 504:    Number of sectors to load
  23.  *       Word at 506:    start of data of menu in clicks
  24.  *       Word at 508:    0
  25.  *       Word at 510:    start of text of menu in clicks
  26.  *
  27.  *    2. Build writes a table into the first 8 words of the kernel's
  28.  *       data space.  It has 4 entries, the text and data size in clicks for each
  29.  *       program.  The kernel needs this information to run mm, fs, and
  30.  *       init.
  31.  *
  32.  *      3. The origin and size of the init program are patched into bytes 4-9
  33.  *         of the file system data space. The file system needs this
  34.  *         information, and expects to find it here.
  35.  *
  36.  * Build is called by:
  37.  *
  38.  *      build bootblok kernel mm fs init menu image
  39.  *
  40.  * to get the resulting image onto the file "image".
  41.  */
  42.  
  43. #include "outmix.h"
  44.  
  45. #ifdef TOS
  46. #include "fakeunix.c"
  47. #else
  48. long    lseek();
  49. #endif
  50.  
  51. #define PROGRAMS 5              /* kernel + mm + fs + init + menu = 5 */
  52. #define PROG_ORG    0           /* where does kernel begin in abs mem */
  53. #define SECTOR_SIZE 512         /* size of buf */
  54. #define READ_UNIT 512           /* how big a chunk to read in */
  55. #define KERNEL_D_MAGIC 0x526F   /* identifies kernel data space */
  56. #define FS_D_MAGIC 0xDADA    /* identifies fs data space */
  57. #define CLICK_SIZE 256
  58. #define CLICK_SHIFT 8
  59. #define KERN 0
  60. #define MM   1
  61. #define FS   2
  62. #define INIT 3
  63. #define FSCK 4
  64.  
  65. int image;                      /* file descriptor used for output file */
  66. int cur_sector;                 /* which 512-byte sector to be written next */
  67. int buf_bytes;                  /* # bytes in buf at present */
  68. char buf[SECTOR_SIZE];          /* buffer for output file */
  69. char zero[SECTOR_SIZE];         /* zeros, for writing bss segment */
  70.  
  71. long cum_size;                  /* Size of kernel+mm+fs+init */
  72. long all_size;                  /* Size of all 5 programs */
  73.  
  74. struct sizes {
  75.   long text_size;               /* size in bytes */
  76.   long data_size;               /* size in bytes */
  77.   long bss_size;                /* size in bytes */
  78.   short  secs;            /* #sectors written */
  79.   short  nulls;            /* #sectors not written */
  80. } sizes[PROGRAMS];
  81.  
  82. char *name[] = {"\nkernel", "mm    ", "fs    ", "init  ", "menu  "};
  83.  
  84. main(argc, argv)
  85. int argc;
  86. char *argv[];
  87. {
  88. /* Copy the boot block and the 5 programs to the output. */
  89.  
  90.   int i;
  91.  
  92.   if (argc != PROGRAMS+3) pexit("seven file names expected. ", "");
  93.  
  94.   create_image(argv[7]);              /* create the output file */
  95.  
  96.   /* Go get the boot block and copy it to the output file or diskette. */
  97.   copy1(argv[1]);
  98.  
  99.   /* Copy the 5 programs to the output file or diskette. */
  100.   for (i = 0; i < PROGRAMS; i++) copy2(i, argv[i+2]);
  101.   flush();
  102.   printf("                                               -----     -----\n");
  103. #ifdef PCIX
  104.   printf("Operating system size  %29ld     %5lx\n", cum_size, cum_size);
  105.   printf("\nTotal size including menu is %ld.\n", all_size);
  106. #else
  107.   printf("Operating system size  %29D     %5X\n", cum_size, cum_size);
  108.   printf("\nTotal size including menu is %D.\n", all_size);
  109. #endif
  110.  
  111.   /* Make the three patches to the output file or diskette. */
  112.   patch1(all_size);
  113.   patch2();
  114.   patch3();
  115.   exit(0);
  116. }
  117.  
  118.  
  119.  
  120. copy1(file_name)
  121. char *file_name;
  122. {
  123. /* Copy the specified file to the output.  The file has no header.  All the
  124.  * bytes are copied, until end-of-file is hit.
  125.  */
  126.  
  127.   int fd, bytes_read;
  128.   char inbuf[READ_UNIT];
  129.  
  130.   if ( (fd = open(file_name, 0)) < 0) pexit("can't open ",file_name);
  131.  
  132.   do {
  133.         bytes_read = read(fd, inbuf, READ_UNIT);
  134.         if (bytes_read < 0) pexit("read error on file ", file_name);
  135.         if (bytes_read > 0) wr_out(inbuf, bytes_read);
  136.   } while (bytes_read > 0);
  137.   flush();
  138.   close(fd);
  139. }
  140.  
  141.  
  142. copy2(num, file_name)
  143. int num;                        /* which program is this (0 - 4) */
  144. char *file_name;                /* file to open */
  145. {
  146. /* Open and read a file, copying it to output.  First read the header,
  147.  * to get the text, data, and bss sizes.
  148.  * Read in all of text and initialized data. Perform relocation.
  149.  * Write the text, data, and bss to output.  The sum of these three pieces
  150.  * must be padded upwards to a multiple of CLICK_SIZE, if need be.  The individual
  151.  * pieces need not be multiples of CLICK_SIZE bytes.
  152.  */
  153.  
  154.   int fd, count, rest, filler;
  155.   unsigned length, n1;
  156.   long reloffset, reloshift, tot_bytes;
  157.   char *buf1, buf2[1024];
  158.   register char *p1, *p2;
  159.   register c, n2;
  160.   struct exec exec;
  161.   long b4;
  162.   extern char *malloc();
  163.   
  164.   if ( (fd = open(file_name, 0)) < 0) pexit("can't open ", file_name);
  165.  
  166.   /* Read the header to see how big the segments are. */
  167.   read_header(fd, &exec, file_name);
  168.  
  169.   reloshift = cum_size;
  170.   reloffset = SZ_HEAD + exec.a_tsize + exec.a_dsize + exec.a_ssize;
  171.  
  172.   /* Pad the total size to a CLICK_SIZE-byte multiple, if needed. */
  173.   tot_bytes = exec.a_tsize + exec.a_dsize + exec.a_bsize;
  174.   rest = (int)(tot_bytes % CLICK_SIZE);
  175.   filler = (rest > 0 ? CLICK_SIZE - rest : 0);
  176.   exec.a_bsize += filler;
  177.   tot_bytes += filler;
  178.   if (num < FSCK) cum_size += tot_bytes;
  179.   all_size += tot_bytes;
  180.  
  181.   /* Record the size information in the table. */
  182.   sizes[num].text_size = exec.a_tsize;
  183.   sizes[num].data_size = exec.a_dsize;
  184.   sizes[num].bss_size  = exec.a_bsize;
  185.   sizes[num].secs      = cur_sector;
  186.  
  187.   /* Print a message giving the program name and size, except for menu. */
  188.   if (num < FSCK) { 
  189.         printf("%s  text=%5D  data=%5D  bss=%5D  tot=%5D  hex=%4X\n",
  190.                 name[num],
  191.         exec.a_tsize, exec.a_dsize, exec.a_bsize,
  192.         tot_bytes, tot_bytes);
  193.   }
  194.  
  195.   /* Read in relocation info from the exec file and relocate.
  196.    * Relocation info is in GEMDOS format. Only longs can be relocated.
  197.    *
  198.    * The GEMDOS format starts with a long L: the offset to the
  199.    * beginning of text for the first long to be relocated.
  200.    * If L==0 then no relocations have to be made.
  201.    *
  202.    * The long is followed by zero or more bytes. Each byte B is
  203.    * processed separately, in one of the following ways:
  204.    *
  205.    * B==0:
  206.    *    end of relocation
  207.    * B==1:
  208.    *    no relocation, but add 254 to the current offset
  209.    * B==0bWWWWWWW0:
  210.    *    B is added to the current offset and the long addressed
  211.    *    is relocated. Note that 00000010 means 1 word distance.
  212.    * B==0bXXXXXXX1:
  213.    *    illegal
  214.    */
  215.  
  216.   /* Allocate memory and read in the text+data and relocation */
  217.   length = exec.a_tsize + exec.a_dsize;
  218.   if (length != exec.a_tsize + exec.a_dsize)
  219.     pexit("more than 64k ", file_name);
  220.   buf1 = malloc(length);
  221.   if (buf1 == 0)
  222.     pexit("too big ", file_name);
  223.   p1 = buf1;
  224.   n1 = length;
  225.   while (n1 != 0) {
  226.     count = (n1 < 16*1024 ? n1 : 16*1024);
  227.     if (read(fd, p1, count) != count)
  228.         pexit("read error on file ", file_name);
  229.     n1 -= count;
  230.     p1 += count;
  231.   }
  232.   if (lseek(fd, reloffset, 0) < 0)
  233.     pexit("can't seek ", file_name);
  234.   p1 = buf1;
  235.   p2 = buf2;
  236.   n2 = read(fd, p2, (int)sizeof(buf2));
  237.   if (n2 < (int)sizeof(long))
  238.     pexit("relocation info missing on file ", file_name);
  239.   if (*((long *)p2) != 0) {
  240.     p1 += *((long *)p2);
  241.     n2 -= (int)sizeof(long);
  242.     p2 += (int)sizeof(long);
  243.     for (;;) {            /* once per relocation */
  244.         if (p1 < buf1 || p1 >= &buf1[length])
  245.             pexit("bad relocation in ", file_name);
  246.         getstruc((char *)&b4, "M4", p1);
  247. /* printf("%X L: %X